﻿using System;
using System.Linq;
using System.Windows;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Markup;
using System.Windows.Media;

namespace HeritageAcademy.Library.Converters
{
    public class FlowDocumentToDocumentPaginatorConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            var document = value as FlowDocument;
            return document != null ? (document as IDocumentPaginatorSource).DocumentPaginator : DependencyProperty.UnsetValue;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return DependencyProperty.UnsetValue;
        }
    }

    public class ColorToBrushConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (value is Color)
            {
                var v = (Color)value;
                return new SolidColorBrush(v);
            }

            return DependencyProperty.UnsetValue;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return DependencyProperty.UnsetValue;
        }
    }

    public class MultiplyConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return values.Where(v => v != DependencyProperty.UnsetValue).Select(ToDouble).Where(d => d != null).Aggregate<double?, double>(1, (current, d) => current * d.Value);
        }

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
        {
            return null;
        }

        private static double? ToDouble(object obj)
        {
            try
            {
                return double.Parse(obj.ToString());
            }
            catch 
            {
                return null;
            }
        }
    }

    public class MultiplyByParameterConverter : IValueConverter
    {
        private static double? ToDouble(object obj)
        {
            try
            {
                return double.Parse(obj.ToString());
            }
            catch
            {
                return null;
            }
        }

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            var v = ToDouble(value);
            var p = ToDouble(parameter);
            if (v != null & p != null)
                return UseRounding ? Math.Round(v.Value * p.Value, 0) : v.Value * p.Value;
            return DependencyProperty.UnsetValue;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return DependencyProperty.UnsetValue;
        }

        public bool UseRounding { get; set; }
    }

    public class BoolToBoolConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (value is bool) return (bool)value;
            return true;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (value is bool) return (bool)value;
            return true;
        }
    }

    public class BoolToVisibilityConverter : IValueConverter
    {
        public bool IsInverted { get; set; }

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return value is bool && (bool)value
                       ? (IsInverted ? Visibility.Collapsed : Visibility.Visible)
                       : (IsInverted ? Visibility.Visible : Visibility.Collapsed);
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return value is Visibility && ((Visibility) value) == Visibility.Visible;
        }
    }

    public class IntToVisibilityConverter : IValueConverter
    {
        public int Threshold { get; set; }

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (typeof(int).IsAssignableFrom(value.GetType()))
            {
                var v = (int)value;
                if (v <= Threshold)
                    return Visibility.Collapsed;
            }
            return Visibility.Visible;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return DependencyProperty.UnsetValue;
        }
    }

    public class HtmlToFlowDocumentConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (value != null)
            {
                var content = XamlReader.Parse(value.ToString()) as FlowDocument;
                return content;
            }
            return value;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return DependencyProperty.UnsetValue;
        }
    }

    public class ZoomToFontSizeConverter : IValueConverter
    {
        public static Double NormalFontSize = 17;

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (value is double)
            {
                var zoom = (double)value;
                return NormalFontSize * zoom / 100;
            }

            return DependencyProperty.UnsetValue;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return DependencyProperty.UnsetValue;
        }
    }

    public class MinCoverter : IValueConverter
    {
        public int? CompareValue { get; set; }

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            double m, v;
            double.TryParse(value.ToString(), out v);

            if (CompareValue == null)
                double.TryParse(parameter.ToString(), out m);
            else
                m = CompareValue.Value;

            return Math.Min(v, m);
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return null;
        }
    }

    public class MaxCoverter : IValueConverter
    {
        public int? CompareValue { get; set; }

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            double m, v;
            double.TryParse(value.ToString(), out v);

            if (CompareValue == null)
                double.TryParse(parameter.ToString(), out m);
            else
                m = CompareValue.Value;

            return Math.Max(v, m);
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return null;
        }
    }
}
